package com.jishuo.nontax.bfc.service;

import com.github.pagehelper.PageHelper;
import com.jishuo.base.bean.BaseResult;
import com.jishuo.base.bean.ErrorCodeEnum;
import com.jishuo.base.bean.Pagination;
import com.jishuo.base.bean.vo.UserVO;
import com.jishuo.base.config.NonTaxConfig;
import com.jishuo.base.dao.UserMapper;
import com.jishuo.base.service.SequenceService;
import com.jishuo.base.util.CommonUtil;
import com.jishuo.base.util.ExportSXSSFUtil;
import com.jishuo.base.util.StringUtil;
import com.jishuo.nontax.bean.bank.PayDivide;
import com.jishuo.nontax.bean.message.*;
import com.jishuo.nontax.bean.vo.BankStationVO;
import com.jishuo.nontax.bean.vo.PayDivideVO;
import com.jishuo.nontax.bean.vo.PayScaleBillVO;
import com.jishuo.nontax.bfc.dao.BaseDataMapper;
import com.jishuo.nontax.bfc.dao.DivideMapper;
import com.jishuo.nontax.bfc.dao.SpecialMapper;
import com.jishuo.nontax.bfc.pzk.PzkService;
import com.jishuo.nontax.bfc.tlq.MessageFactory;
import com.jishuo.nontax.bfc.tlq.MessageService;
import com.jishuo.nontax.util.PzkUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author :hanlipeng
 * @description :
 * @create :2022-12-22 11:23:00
 */
@Service
public class DivideService {

    private static Logger logger = LoggerFactory.getLogger(DivideService.class);


    @Resource
    private DivideMapper divideMapper;
    @Resource
    private SequenceService sequenceService;
    @Resource
    private MessageService messageService;
    @Resource
    private NonTaxConfig nonTaxConfig;
    @Resource
    private SpecialMapper specialMapper;
    @Resource
    private BaseDataMapper baseDataMapper;
    @Resource
    private PzkService pzkService;
    @Resource
    private PzkUtils pzkUtils;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 划解分成缴费信息
     *
     * @param dividebillnum 票据号
     * @param bankaffirm    交易流水号
     * @param paybankdt     交易时间
     * @param bankstation   网点
     * @return
     */
    public BaseResult setDividePayInfo(String dividebillnum, String bankaffirm, String paybankdt, String bankstation) {

        PayDivideVO divideInfo = divideMapper.findtBankDivideAffirm(dividebillnum);
        //xml解析器
        Serializer serializer = new Persister();
        //xml转换器
        StringWriter sw = new StringWriter();
        // 已缴费直接返回已缴费
        if (Integer.valueOf(1).equals(divideInfo.getIsbankaffirm())) {
            return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        }
        try {
            //更新化解分成
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            divideInfo.setMessageid(messageid);
            divideInfo.setBankaffirm(bankaffirm);
            divideInfo.setIsbankaffirm(1);
            divideInfo.setPaybankdt(paybankdt);
            divideInfo.setBankstation(bankstation);
            divideInfo.setSendtime(sdf.format(new Date()));
            int i = divideMapper.updateDivideBankAffirm(divideInfo);
            if (i < 1) return new BaseResult(ErrorCodeEnum.DB_ERR.getCode(), "更新划解国库单据失败（" + dividebillnum + "）");

            SetBankPayDivide setBankPayDivide = divideInfo.setDividePayInfo();
            serializer.write(setBankPayDivide, sw);
            //发送财政
            Object obj = MessageFactory.setDividePayInfo(divideInfo);
            messageService.sendMessage("SETBANKPAYDIVIDE", messageid, obj, "2.0");

            pzkService.savePzmsg("SETPAYDIVIDEPZK", pzkUtils.getDividePzk(divideInfo));
        } catch (Exception e) {
            logger.info("划解分成失败：" + e.toString());
            return new BaseResult(ErrorCodeEnum.TLQ_ERR);
        }
        return new BaseResult();
    }


    /**
     * @param dividebillnum 票据号
     * @auther dinggaofei
     * @Date 2022/12/23 15:33
     * @description 记录划解分成票据, 并向财政获取划解分成单据信息
     */
    public BaseResult getPayDivide(String dividebillnum) {

        PayDivideVO divideInfo = divideMapper.findDivideInfo(dividebillnum);
        //xml解析器
        Serializer serializer = new Persister();
        //xml转换器
        StringWriter sw = new StringWriter();
        try {
            BaseResult ret = new BaseResult();
            //已缴费的直接返回
            if (divideInfo != null && divideInfo.getBillstate() == 3) {
                PayDivide payDivide = new PayDivide();
                payDivide.setDividebillnum(dividebillnum);
                payDivide.setBillstate("3");
                serializer.write(payDivide, sw);
                ret.setData(sw.toString());
                return ret;
            }
            //更新messageid
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            if (divideInfo == null) {
                long patid = sequenceService.getNextSeq("FSPAYDIVIDESEQ");
                divideInfo = new PayDivideVO();
                divideInfo.setPayid(patid);
                divideInfo.setDividebillnum(dividebillnum);
                divideInfo.setMessageid(messageid);
                divideMapper.insertBlankDivide(divideInfo);
            } else {
                divideInfo.setMessageid(messageid);
                divideMapper.updateMsgDivide(divideInfo);
            }
            //从财政查询
            boolean suc = messageService.sendAndRecvMessage("GETPAYDIVIDE", messageid, MessageFactory.getPayDivide(dividebillnum), "2.4");
            if (suc) {
                divideInfo = divideMapper.findDivideInfo(dividebillnum);
                PayDivide payDivide = divideInfo.getPayDivide();
                serializer.write(payDivide, sw);
                ret.setData(sw.toString());
                return ret;
            }
            return null;
        } catch (Exception e) {
            logger.info("失败：" + e.toString());
            return null;
        }

    }


    public void setPayDivide(String data, int billstate, String sn) {
        if (billstate == 1) {
            try {
                //xml解析器
                Serializer serializer = new Persister();
                //返回缴款书对象
                SetPayDivide payDivide = serializer.read(SetPayDivide.class, new StringReader(data));
                PayDivideVO payDivideVO = new PayDivideVO(payDivide);
                payDivideVO.setBillstate(billstate);
                payDivideVO.setIssend(2);
                if (divideMapper.findDivideCount(payDivideVO.getDividebillnum()) > 0) {
                    divideMapper.updateDivide(payDivideVO);
                } else {
                    long payid = sequenceService.getNextSeq("FSPAYDIVIDESEQ");
                    payDivideVO.setPayid(payid);
                    divideMapper.insertDivide(payDivideVO);
                }

            } catch (Exception e) {
                logger.info("失败：" + e.toString());
            }
        } else if (billstate > 1) {
            divideMapper.updateDivideState(sn, billstate);
        }
    }


    public void setPayDivideNew(String data, int billstate, String sn) {
        //xml解析器
        Serializer serializer = new Persister();
        try {

            //正常
            if (billstate == 1) {
                SetPayDivideNew divide = serializer.read(SetPayDivideNew.class, new StringReader(data));
                PayDivideVO payDivideVO = new PayDivideVO(divide);
                payDivideVO.setBillstate(billstate);
                payDivideVO.setIssend(2);
                if (divideMapper.findDivideCount(payDivideVO.getDividebillnum()) > 0) {
                    divideMapper.updateDivide(payDivideVO);
                } else {
                    long payid = sequenceService.getNextSeq("FSPAYDIVIDESEQ");
                    payDivideVO.setPayid(payid);
                    divideMapper.insertDivide(payDivideVO);
                }
            } else {
                divideMapper.updateDivideState(sn, billstate);
            }
        } catch (Exception e) {
            logger.info("失败：" + e.toString());
        }
    }

    /**
     * 划解分成缴费
     * dividebillnum 票号
     * bankaffirm 交易流水号
     * paybankdt 交易时间
     * bankstation 网点
     * chkBankaffirm 是否校验流水号
     */

    public int setIllegalactivityScaleBackOut(SetBankIllegalactivityScaleinfoBackOut div) {

        try {
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");

            //发送到财政
            messageService.sendMessage("SETBANKILLEGALACTIVITYSCALEINFOBACKOUT", messageid, div, "2.0");
            // 写凭证
            if (nonTaxConfig.IS_Pzk) {
                PzkService.sendPzk("SETBANKILLEGALACTIVITYSCALEINFOBACKOUTPZK", div);
            }

            return 1;
        } catch (Exception e) {
            logger.info("失败：" + e.toString());
            return 0;
        }
    }

    public BaseResult sendIllegalactivityScaleBankaffirm(String billnum) {

        //xml解析器
        Serializer serializer = new Persister();
        //xml转换器
        StringWriter sw = new StringWriter();

        try {
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            //获取缴款书对象
            ArrayList<PayScaleBillVO> scale = specialMapper.findIllScaleSend(billnum, null);

            Object obj = MessageFactory.getSetBankIllegalactivityScaleinfo(scale);
            messageService.sendMessage("SETBANKILLEGALACTIVITYSCALEINFO", messageid, obj, "2.0");

            // 写凭证
            if (nonTaxConfig.IS_Pzk) {
                PzkService.sendPzk("SETBANKILLEGALACTIVITYSCALEINFOPZK", obj);
            }
            return new BaseResult();
        } catch (Exception e) {
            logger.info("失败：" + e.toString());
            return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
        }
    }
//页面

    /**
     * 获取单据列表
     *
     * @param payDivideVO
     * @return
     */
    public List<PayDivideVO> findDividePage(PayDivideVO payDivideVO, Pagination pagination) {
        if (pagination.getRows() > 0) PageHelper.startPage(pagination.getPage(), pagination.getRows());
        return this.divideMapper.findDividePage(payDivideVO);
    }

    public PayDivideVO getDivide(Long payid) {

        PayDivideVO payDivideVO = divideMapper.getDivide(payid);
        return payDivideVO;
    }

    public BaseResult saveDivide(PayDivideVO payDivideVO) {
        int n = divideMapper.saveDivide(payDivideVO);
        if (n < 1) return new BaseResult(ErrorCodeEnum.DB_ERR);
        return new BaseResult();
    }

    //发送
    public BaseResult sendDivide(String billids) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<PayDivideVO> dividePage = divideMapper.findDivide(ids);
        for (PayDivideVO vos : dividePage
        ) {

            return setDividePayInfo(vos.getDividebillnum(), vos.getBankaffirm(), vos.getPaybankdt(), vos.getBankstation());
        }
        return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
    }

    //冲销
    public BaseResult cleanDivide(String billids, String usercode) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<PayDivideVO> list = divideMapper.findDivide(ids);

        Calendar cal = Calendar.getInstance();
        String cxTime = sdf.format(cal.getTime());
        cal.add(Calendar.MINUTE, 0 - nonTaxConfig.CxTime);
        String chkTime = sdf.format(cal.getTime());

        String errinfo = "";
        for (PayDivideVO vo : list) {
            if (StringUtil.isEmpty(vo.getSendtime()) || chkTime.compareTo(vo.getSendtime()) < 0) {
                setDivideBackOut(cxTime, usercode, vo);
                divideMapper.updateIsBankaffirm(vo.getPayid());
            } else {
                errinfo += vo.getDividebillnum() + ",";
            }

        }
        if (!errinfo.equals("")) {
            errinfo += "超时冲销失败,其他单据冲销成功!";
            return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), errinfo);
        } else {
            errinfo = "冲销成功";
            return new BaseResult(ErrorCodeEnum.SUCCESS.getCode(), errinfo);
        }

    }

    private BaseResult setDivideBackOut(String backoutdt, String backoutname, PayDivideVO payDivideVO) {
        try {
            Serializer serializer = new Persister();
            StringWriter sw = new StringWriter();
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            SetBankPayDivideBackOut obj = (SetBankPayDivideBackOut) MessageFactory.getSetDivideBackOut(payDivideVO);
            obj.setRemark("");
            obj.setBackoutname("");
            serializer.write(obj, sw);
            messageService.sendMessage("SETBANKPAYDIVIDEBACKOUT", messageid, obj, "2.0");
            if (nonTaxConfig.IS_Pzk) {
                PzkService.sendPzk("SETBANKPAYDIVIDEBACKOUTPZK", obj);
            }
        } catch (Exception e) {
            logger.info("划解分成失败：" + e.toString());
            return new BaseResult(ErrorCodeEnum.TLQ_ERR);
        }
        return new BaseResult();
    }

    public void divideExport(long bankid, String paybankdt, HttpServletResponse response) {
        if (bankid == 0 || StringUtil.isEmpty(paybankdt)) return;
        PayDivideVO vo = new PayDivideVO();
        vo.setPayerbankid(bankid);
        vo.setPaybankdt(paybankdt);
        List<PayDivideVO> dividePage = divideMapper.findDividePage(vo);
        String[] headers = {"流水号", "票据号", "付款人行政区划", "付款人区划编码", "付款人区划名称", "缴款开户银行流水号", "付款人银行名称", "付款人账户名称", "付款人账号", "付款人单位id", "付款人单位（部门）编码", "付款人单位（部门）名称", "收款人行政区划", "收款人行政区划编码", "收款人行政区划名称", "收款人开户行id", "收款人开户行", "收款人账户", "收款人账号", "收款人单位id", "收款人单位（部门）编码", "收款人单位（部门）名称", "项目id", "项目编码", "项目名称", "项目金额", "银行划款时间", "银行网点", "银行交易流水号", "单据状态", "发送时间", "__status", "银行核心交易流水号", "是否发送"};
        String[] col = {"payid", "dividebillnum", "payercantonid", "payercantoncode", "payercantonname", "paye", "payerbankname", "payeraccountname", "payeraccountcode", "", "unitid", "payerunitcode", "payerunitname", "payeecantonid", "payeecantoncode", "payeecantonname", "payeebankid", "payeebankname", "payeeaccountname", "payeeaccountcode", "unitid", "unitcode", "unitname", "itenid", "itencode", "itemname", "itemoney", "paybankdt", "bankstation", "bankaffirm", "billstate", "dendtime", "__status", "hxbankaffirm", "issend"};
        ExportSXSSFUtil ex = new ExportSXSSFUtil();
        SXSSFWorkbook workbook = ex.exportExcelSXSSF("划解分成列表", headers, col, dividePage, null);
        response.setContentType("application/vnd.ms-excel");
        try {
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    new String(("划解分成列表.xls").getBytes(), "iso-8859-1"));
            OutputStream ouputStream = response.getOutputStream();
            workbook.write(ouputStream);
            ouputStream.flush();
            ouputStream.close();
        } catch (Exception e) {
            logger.info("导出失败：" + e.toString());
        }
    }

    /**
     * 划解分成收款
     *
     * @param dividebillnum
     * @param user
     * @return
     */
    public BaseResult payDividePayView(String dividebillnum, UserVO user) {

        try {
            CommBankService cbs = new CommBankService();

            Map<String, String> rtnBank = cbs.processPayDividePay();
            BankStationVO bankStationVO = baseDataMapper.getBankStation(user.getBankStationId());

            String paybankdt = rtnBank.get("hx_paybankdt");
            String bankaffirm = rtnBank.get("hx_bankaffirm");
            String bankstation = bankStationVO.getBankstationcode();
            BaseResult result = setDividePayInfo(dividebillnum, bankaffirm, paybankdt, bankstation);
            if (result.isSuccess()) {
                divideMapper.updateDivideHxBankaffirm(dividebillnum, bankaffirm);
            }
            return result;
        } catch (Exception e) {
            return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), "缴费异常");
        }

    }
}
